// fiber_echo_client.cpp
#include <boost/fiber/all.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <string>

using namespace boost::asio;
using namespace boost::asio::ip;

class EchoClient {
private:
    io_context& io_context_;
    tcp::socket socket_;

public:
    EchoClient(io_context& io_context, const std::string& host, short port)
        : io_context_(io_context), socket_(io_context) {
        
        // 解析地址并连接
        tcp::resolver resolver(io_context_);
        auto endpoints = resolver.resolve(host, std::to_string(port));
        
        boost::asio::connect(socket_, endpoints);
        std::cout << "Connected to " << host << ":" << port << std::endl;
    }

    void start() {
        // 创建 fiber 来处理客户端逻辑
        boost::fibers::fiber reader([this]() { read_loop(); });
        boost::fibers::fiber writer([this]() { write_loop(); });
        
        reader.join();
        writer.join();
    }

private:
    void read_loop() {
        try {
            std::array<char, 1024> buffer;
            while (true) {
                boost::system::error_code ec;
                // 1. 发起异步读取
                size_t length = socket_.async_read_some(
                    boost::asio::buffer(buffer),
                    boost::fibers::asio::yield[ec]
                );
                // 2. fiber 在这里被挂起，直到数据到达
                // 3. 当数据到达时，fiber 被自动恢复
                // 4. 函数从这里继续执行

                if (ec == boost::asio::error::eof) {
                    std::cout << "Server closed connection" << std::endl;
                    break;
                } else if (ec) {
                    std::cerr << "Read error: " << ec.message() << std::endl;
                    break;
                }

                std::cout << "Echo received: " << std::string(buffer.data(), length);
            }
        } catch (const std::exception& e) {
            std::cerr << "Read exception: " << e.what() << std::endl;
        }
    }

    void write_loop() {
        try {
            std::string line;
            while (std::getline(std::cin, line)) {
                if (line.empty()) continue;
                
                line += "\n";  // 添加换行符
                
                boost::system::error_code ec;
                boost::asio::async_write(
                    socket_,
                    boost::asio::buffer(line),
                    boost::fibers::asio::yield[ec]
                );

                if (ec) {
                    std::cerr << "Write error: " << ec.message() << std::endl;
                    break;
                }
                
                std::cout << "Sent: " << line;
            }
        } catch (const std::exception& e) {
            std::cerr << "Write exception: " << e.what() << std::endl;
        }
    }
};

int main() {
    try {
        io_context io_context;
        
        // 初始化 fiber 调度器
        boost::fibers::use_scheduling_algorithm<boost::fibers::asio::round_robin>(io_context);
        
        EchoClient client(io_context, "127.0.0.1", 8080);
        client.start();
        
    } catch (std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
    
    return 0;
}